package com.atguigu.paymentdemo.uitl;

import com.google.gson.Gson;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Component
public class WechatPayRequest2Validator {
    protected static final Logger log = LoggerFactory.getLogger(com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator.class);
    protected static final long RESPONSE_EXPIRED_MINUTES = 5L;
    @Resource
    protected  Verifier verifier;
    @Resource
    Gson gson;

    protected static IllegalArgumentException parameterError(String message, Object... args) {
        message = String.format(message, args);
        return new IllegalArgumentException("parameter error: " + message);
    }

    protected static IllegalArgumentException verifyFail(String message, Object... args) {
        message = String.format(message, args);
        return new IllegalArgumentException("signature verify fail: " + message);
    }

    /**
     * 验签
     * @param request
     * @param requestBody
     * @return
     * @throws IOException
     */

    public final boolean validate(HttpServletRequest request, String requestBody) throws IOException {
        try {
            //验证参数非空
            this.validateParameters(request,gson.fromJson(requestBody,HashMap.class));
            //构造签名串
            String message = this.buildMessage(request,requestBody);
            //获取用于验签的参数
            String serial = request.getHeader("Wechatpay-Serial");
            String signature = request.getHeader("Wechatpay-Signature");
            //验签
            if (!this.verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
                throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]", serial, message, signature, request.getHeader("Request-ID"));
            } else {
                return true;
            }
        } catch (IllegalArgumentException var5) {
            log.warn(var5.getMessage());
            return false;
        }
    }

    /**
     * 验证相关参数非空
     * @param request
     * @param requestBody
     */

    protected final void validateParameters(HttpServletRequest request, Map<String,Object> requestBody) {

        if (requestBody == null) {
            throw parameterError("支付通知参数为空");
        } else {
            String requestId = (String) requestBody.get("id");
            String[] headers = new String[]{"Wechatpay-Serial", "Wechatpay-Signature", "Wechatpay-Nonce", "Wechatpay-Timestamp"};
            int var = headers.length;

            for(int i = 0; i < var; ++i) {
                String headerName = headers[i];
                if (request.getHeader(headerName) == null) {
                    throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
                }
            }
            //支付超时判断
            String timestampStr = request.getHeader("Wechatpay-Timestamp");

            try {
                Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
                if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
                    throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
                }
            } catch (NumberFormatException | DateTimeException var10) {
                throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
            }
        }
    }

    /**
     * 构造签名串
     * @param request
     * @param requestBody
     * @return
     * @throws IOException
     */

    protected final String buildMessage(HttpServletRequest request,String requestBody) throws IOException {
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String body = requestBody;
        return timestamp + "\n" + nonce + "\n" + body + "\n";
    }

}
